/*
 * Spoof Airport MAC address
 *
 * Copyright (c) 2008 Michael Santos <michael.santos@gmail.com>
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <err.h>

#include <sys/types.h>
#include <sys/param.h>

#include <net/ethernet.h>

#include <openssl/rand.h>
#include <openssl/err.h>

#define AIRPORT_DRIVER  "AppleAirPort2.kext/Contents/MacOS/AppleAirPort2"
#define AIRPORT_PATCHED AIRPORT_DRIVER "-patch"
#define KEXT_DIR        "/System/Library/Extensions"

#define TMPDIR          "/tmp/spoof.XXXXXX"

#define FREAD(w,x,y,z) do { \
    if (fread(w, x, y, z) != y) { \
        if (feof(z) != 0) { \
                errx(EXIT_FAILURE, "Reached EOF, patch failed"); \
        } \
        if (ferror(z) != 0)  { \
            err(EXIT_FAILURE, "Error reading file"); \
        } \
        errx(EXIT_FAILURE, "Unknown error"); \
    } \
} while (0);

#define FWRITE(w,x,y,z) do { \
    if (fwrite(w, x, y, z) != y) { \
        err(EXIT_FAILURE, "fwrite"); \
    } \
} while (0);

#define SYSTEM(x) do { \
    switch (system((x))) { \
        case 0: \
                break;\
        case -1: \
                 errx(EXIT_FAILURE, "Unable to fork"); \
        case 127: \
                  errx(EXIT_FAILURE, "Unable to exec shell"); \
        default: \
                 errx(EXIT_FAILURE, "Command failed: %s", #x); \
    }; \
} while (0);

#define IS_ERR(x) do { \
    if ((x) == -1) { \
        err(EXIT_FAILURE, "%s", #x); \
    } \
} while (0)

#define IS_NULL(x) do { \
    if ((x) == NULL) { \
        err(EXIT_FAILURE, "%s", #x); \
    } \
} while (0)

#define VERBOSE(x, ...) do { \
    if (verbose >= x) { \
        (void)fprintf (stderr, __VA_ARGS__); \
    } \
} while (0)

void print_MAC(u_char *buf);
char *sp_copy(char *tmpl);
void sp_patch(u_char *mac);
void sp_move(char *src, char *dst);
void sp_reload(char *path);
void sp_cleanup(char *path);
void usage(void);

enum {
    EOF_BREAK,
    EOF_ERR,
};

char search[] = {
    0x88, 0xFF, 0x19, 0x90, 0x89, 0x7F, 0x19, 0x91, 0x89, 0x5F, 0x19, 0x92, 0x89, 0x1F, 0x19, 0x93,
    0x7C, 0xE0, 0x58, 0x38, 0x89, 0x3F, 0x19, 0x94, 0x7D, 0x40, 0x00, 0x38, 0x88, 0x5F, 0x19, 0x95,
    0x7D, 0x00, 0x00, 0x38, 0x7D, 0x20, 0x00, 0x38, 0x7C, 0x40, 0x00, 0x38, 0x2F, 0x80, 0x00, 0xFF,
    0x41, 0x9E, 0x01, 0xCC,
};

char patch[] = {
    0x3C, 0xE0, 0x0A, 0x0A, 0x90, 0xFF, 0x19, 0x90, 0x3C, 0xE0, 0x0A, 0x0A, 0x60, 0xE7, 0x0A, 0x0A,
    0x90, 0xFF, 0x19, 0x92, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
    0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
    0x60, 0x00, 0x00, 0x00,
};

